"use strict"
/// <reference path="../../../index.d.ts" />
const Controller = require("egg").Controller
let {md5, getToDay, sendStat} = require("../../extend/helper")
let gameConfig = require("../../../config/game")
let {limitNum, limitTime} = gameConfig

class Base extends Controller {
	constructor(ctx) {
		super(ctx)
		this.constant = this.config.constant
		this.serverConfig = this.config.serverConfig
		this.AssistData = this.app.model.Game.AssistData
		this.GameUser = this.app.model.Game.GameUser
		this.ShareInfo = this.app.model.ShareInfo
		this.GameUserSign = this.app.model.Game.GameUserSign
		this.empireServer = this.service.empire
	}

	async getUserData() {
		let {ctx, config} = this
		let oid = ctx.userInfo.oid
		let key = config.redisPrefix.gameUser + oid
		let userData = await ctx.service.empire.getGameUserCache(oid)
		let new_player = false
		if (!userData) {
			let res = []
			try {
				res = await this.empireServer.findOrCreateUser(oid)
			} catch (error) {
				ctx.body = sendStat(config.constant.ERROR_PERMISS_NOT_ALLOWED, "创建用户失败/未授权")
				ctx.logger.error("创建用户失败")
				return
			}
			userData = res[0]
			new_player = res[1]
		}
		// let res = await ctx.service.empire.getSignReward(oid)

		let {total_coin, popularity, sycee, last_login, sell_count, unlock_map} = userData
		userData.last_login = Date.now()
		await ctx.app.redis.set(key, JSON.stringify(userData))// 保存
		ctx.body = sendStat(this.constant.NORMAL, {total_coin, unlock_map, popularity, sycee, last_login, now_login: Date.now(), sell_count, new_player})//signTime: (res && res.signTime) || 0,
	}

	async updateUserData() {
		let {ctx} = this
		let body = ctx.request.body
		ctx.validate({
			total_coin: "pnumstr",
			popularity: "pnumstr",
			sycee: "pnumstr",
			hash: "alphanum"
		}, body)

		let arrMap = ["total_coin", "popularity", "sycee"]
		let str = arrMap.map((str) => {
			return str + ":" + body[str]
		}).join("\n") + "\ntime:" + parseInt(Date.now() / 1000 / 60)

		let md5Str = md5(str)
		if (md5Str != body.hash) {//
			ctx.status = 422
			let e = new Error()
			e.field = "hash"
			e.message = "hash error"
			ctx.throw(422, e.message, {
				code: "hash",
				errors: [e],
			})
			return
		}

		ctx.gameUser.total_coin = Number(body.total_coin)
		ctx.gameUser.popularity = Number(body.popularity)
		ctx.gameUser.max_total_coin = Math.max(body.total_coin, ctx.gameUser.max_total_coin || 0) // 历史最大的金币数量
		ctx.gameUser.max_popularity = Math.max(body.popularity, ctx.gameUser.max_popularity || 0)

		ctx.gameUser.sycee = Number(body.sycee) < 2147483647 ? Number(body.sycee) : -1
		ctx.gameUser.last_login = Date.now()
		await ctx.gameUser.save()
		ctx.body = sendStat(this.constant.NORMAL, {stat: true})
	}

	async unlockMap() {
		// this.ctx.gameUser.unlock_map = 2
		this.ctx.validate({map_id: "pintstr"}, this.ctx.request.body)
		if (this.ctx.gameUser.unlock_map > Number(this.ctx.request.body.map_id)) {
			this.ctx.logger.warn("解锁地图降级" + this.ctx.gameUser.unlock_map)
		}
		this.ctx.gameUser.unlock_map = Number(this.ctx.request.body.map_id)
		await this.ctx.gameUser.save()
		this.ctx.body = sendStat(this.constant.NORMAL, {
		})
	}

	async getDuringIncome() {
		let user = await this.GameUser.findOne({
			attributes: ["last_login"],
			where: {
				oid: this.ctx.userInfo.oid
			}
		})
		let during_time = Date.now() - user.last_login
		during_time = isNaN(during_time) ? 0 : during_time
		this.ctx.body = sendStat(this.constant.NORMAL, {
			during_time
		})
	}

	// 获取玩家数据
	async outGame() {
		await this.GameUser.update({
			last_login: Date.now()
		}, {
			where: {
				oid: this.ctx.userInfo.oid
			}
		})
		this.ctx.body = sendStat(this.constant.NORMAL, {})
	}

	async toHelp() {
		// 分享链接 ///friend_id //帮助谁的数据 
		let ctx = this.ctx
		let body = ctx.request.body
		let AssistData = this.AssistData
		this.ctx.validate({friend_id: "numstr"}, body)
		if (body.friend_id == ctx.userInfo.oid) {// 自己助力自己
			ctx.body = sendStat(this.constant.EMPIRE_HELP_SET_ERROR)
			return
		}
		let d = getToDay()
		/**
		 * @type {{oid:number,assistTime:number,helpid:number}[]}
		 */
		let userDatas = await AssistData.findAll({
			where: {
				oid: body.friend_id,
				$or: [
					{
						assistTime: null,
					}, {
						assistTime: {
							$gte: d
						}
					}
				]
			}
		})
		// 所有助力
		let userData = userDatas.find((val) => {// 自己目前助力
			return val.helpid == ctx.userInfo.oid
		})

		if (!userData) {
			if (userDatas.length < limitNum + 1) {
				await AssistData.create({
					assistTime: undefined,
					oid: body.friend_id,
					helpid: this.ctx.userInfo.oid
				})
				this.ctx.body = sendStat(this.constant.NORMAL, {msg: "", stat: true})
				try {
					ctx.service.empire.countAssist(body.friend_id)
				} catch (error) {
					ctx.logger.error("统计助力异常" + error)
				}
				return
			}
			else {
				this.ctx.body = sendStat(this.constant.EMPIRE_HELP_FAIL, {msg: "用户上限", stat: false})
			}
			return
		}

		if (userData.time > d) {
			this.ctx.body = sendStat(this.constant.EMPIRE_HELP_FAIL, {msg: "一天只能助力一次", stat: false})
			return
		} else { // 未开启助力debug
			this.ctx.body = sendStat(this.constant.EMPIRE_HELP_FAIL, {msg: "已经正在助力, 等待好友开启 ", stat: false})
		}
		// 超出限制用户
	}

	async startHelper() {
		let body = this.ctx.request.body
		let AssistData = this.AssistData
		this.ctx.validate({helpid: "numstr"}, body)
		// -1 代表机器人
		let d = await AssistData.update(
			{
				assistTime: Date.now(),
			},
			{
				where: {
					helpid: body.helpid,
					oid: this.ctx.userInfo.oid,
					assistTime: null
				}
			}
		)
		this.ctx.logger.warn(d)
		if (d[0])
			this.ctx.body = sendStat(this.constant.NORMAL, {msg: "成功", stat: true})
		else {
			this.ctx.body = sendStat(this.constant.EMPIRE_HELP_MISS, {msg: "失败", stat: false})
		}
	}

	async friendHelpList() {
		let AssistData = this.AssistData
		let oid = this.ctx.userInfo.oid
		let rebotHelpTime = gameConfig.rebotHelpTime / 1000
		let rebot = {
			id: -1, // 好友id, 机器人id: -1
			avatar: null,  // 好友头像
			total_work_time: rebotHelpTime,   // 总的工作时长 默认4小时
			worked_time: 0,       // 已工作的时长
		}
		/** @type {{oid:number,assistTime:number,helpid:number}[]	 */
		let userDatas = await AssistData.findAll({
			include: [{model: this.app.model.ApplicationUser, attributes: ["headimg_url"]}],
			where: {
				oid,
			},
		})

		let d = getToDay()
		let removeIds = []
		let finshIds = []
		let res = userDatas.map((val) => {
			if (val.stat == 1) { // 已经完成了的
				return undefined
			}
			let id = val.helpid
			let avatar = val.applicationUser && val.applicationUser.headimg_url
			let worked_time
			let helpTime = val.helpid == rebot.id ? rebotHelpTime * 1000 : limitTime
			if (val.assistTime != undefined) {
				worked_time = Math.min((Date.now() - val.assistTime) / 1000, helpTime / 1000) //s
				if (Date.now() - val.assistTime > helpTime && val.assistTime < d) {
					removeIds.push(val.id)
				}
				// 最后一次返回时候不为还
				// 已经完成助力的
				if (Date.now() - val.assistTime > helpTime) {
					finshIds.push(val.id)
					val.stat = 1
				}
			} else {
				worked_time = 0
			}
			return {id, avatar, worked_time, total_work_time: helpTime / 1000, assistTime: new Date(val.assistTime).getTime()}  //s
		}).filter(Boolean)
		// 
		let hasRebot = userDatas.find((val) => {
			// 找出机器人是否参与过助力// 今天
			// 或者有未助力机器人数据在服务器 防止 重复发
			return val.helpid == rebot.id && (val.assistTime == undefined || val.assistTime > d)
		})

		if (!hasRebot) {
			res.unshift(rebot)
			let createStat = await AssistData.create({
				oid: this.ctx.userInfo.oid, stat: 0,
				helpid: "-1", assistTime: null
			})
			this.ctx.logger.warn("添加机器人助力结果", JSON.parse(JSON.stringify(createStat)))
		} else {
			res.sort((v1, v2) => {
				return v1.id > v2.id ? 1 : -1
			})
		}
		if (removeIds.length > 0) {
			// 删除超时的
			this.ctx.logger.warn("助力removeIds:" + removeIds)
			await this.service.empire.removeEmpireHelp(removeIds)
		}
		if (finshIds.length > 0) {
			await AssistData.update({
				stat: 1
			}, {
				where: {
					id: {
						$in: finshIds
					}
				}
			})
		}
		this.ctx.body = sendStat(this.constant.NORMAL, res)
	}

	async setInvite() {
		let ctx = this.ctx
		let body = ctx.request.body
		ctx.validate({inviteId: "numstr"}, body)

		ctx.logger.info(`${ctx.gameUser.oid} 设置邀请人:${body.inviteId}`)
		if (ctx.gameUser.inviteid != null) {
			ctx.body = sendStat(this.constant.EMPIRE_USER_SET_INVITE_REPEAT, {
				stat: false,
				msg: "已经设置了邀请人"
			})
			return
		}

		if (body.inviteId == ctx.gameUser.oid) {
			ctx.body = sendStat(this.constant.EMPIRE_USER_SET_INVITER_ERROR, {
				stat: false,
				msg: "说好了邀请自己没有用"
			})
			return
		}

		let inviteUser = await this.GameUser.findOne({
			where: {
				oid: body.inviteId
			},//查找这个人的邀请人数
			attributes: ["oid", "id"]
		})

		if (!inviteUser) {
			ctx.body = sendStat(this.constant.EMPIRE_USER_MISS, {msg: "用户不存在"})
			return
		}
		ctx.gameUser.inviteid = body.inviteId

		await ctx.gameUser.save()
		let invite_num = await this.GameUser.count({
			where: {
				inviteid: body.inviteId
			}
		})
		inviteUser.invite_num = invite_num
		await inviteUser.save()

		ctx.body = sendStat(this.constant.NORMAL, {
			stat: true,
			msg: "设置成功"
		})
	}

	/**
	 * 获取所有邀请的人
	 */
	async getInviteList() {
		let empire = this.service.empire
		let user = await this.GameUser.findAll({
			attributes: ["inviteid", "id", "oid", "invite_num", "invite_reward"],
			include: [{model: this.app.model.ApplicationUser, attributes: ["headimg_url"]}],
			order: ["oid"],
			where: {
				inviteid: this.ctx.userInfo.oid
			}
		})
		let inviteList = user.map((o, i) => {
			let {oid: id} = o
			let obj = empire.getReward(i + 1)
			let avatar = o.applicationUser && o.applicationUser.headimg_url
			let sycee = !obj ? 0 : obj.reward
			let stat = Boolean(o.invite_reward)
			return {avatar, id, stat, sycee}
		})
		this.ctx.body = sendStat(this.constant.NORMAL, inviteList)
	}

	async updateInviteList() {
		this.ctx.validate({id: "numstr"}, this.ctx.request.body)
		let oid = this.ctx.request.body.id
		let user = await this.GameUser.findOne({
			where: {
				oid
			},
			attributes: ["id", "oid", "inviteid", "invite_reward"]
		})
		if (!user) {
			this.ctx.body = sendStat(this.constant.EMPIRE_USER_MISS, {msg: "玩家不存在"})
			return
		} else if (user.inviteid != this.ctx.userInfo.oid) {
			this.ctx.body = sendStat(this.constant.EMPIRE_USER_INVITEER_MISS, {msg: ""})
			return
		} else if (user.invite_reward) {
			this.ctx.body = sendStat(this.constant.EMPIRE_USER_INVITER_REWARD_RECEIVE, {msg: ""})
			return
		} else {
			this.ctx.service.empire.saveOidIfExist(user.oid, {invite_reward: true})
			user.invite_reward = true// 奖励状态
			await user.save()
			this.ctx.body = sendStat(this.constant.NORMAL, {msg: "成功"})
		}
	}

	async test() {
		// console.log(this.ctx.query)
		// this.ctx.body = await this.app.cache.tskList
		// this.app.cache.tskList = undefined
		// let d = await this.service.empire.saveOidIfExist(1, {create_at: 20})
		// let d1 = await this.service.empire.saveOidIfExist(1, {create_at: 30})
		// console.log(d)
		this.ctx.body = {}
		// this.ctx.body = await this.service.empire.existUser(this.ctx.query.oid)
	}
}
module.exports = Base